# 定义编译器
CC = gcc
CXX = g++

# 定义最终生成的可执行文件名称
TARGET = main

# 定义源码和构建目录
SRC_DIR = src
BUILD_DIR = build

# 定义头文件搜索路径 (-I)
INCLUDE_PATHS = -I$(SRC_DIR) -Iinc -Iinc/iflyteksdk

# 定义C和C++的编译标志 (CFLAGS)
# -Wall 开启所有常用警告
CFLAGS = $(INCLUDE_PATHS) -Wall
CXXFLAGS = $(INCLUDE_PATHS) -Wall -std=c++11

# 定义库文件搜索路径 (-L)
LIB_PATHS = -Llib

# 定义需要链接的库 (-l)
LDLIBS = -lSparkChain -ljpeg -lrt -lm -lpthread

# 定义运行时库路径 (rpath), 确保程序能找到 .so 文件
RPATH = -Wl,-rpath,$(shell pwd)/lib

# 自动查找所有 .c 和 .cpp 源文件
SOURCES_C := $(wildcard $(SRC_DIR)/*.c)
SOURCES_CXX := $(wildcard $(SRC_DIR)/*.cpp)

# 根据源文件列表生成对应的目标 (.o) 文件列表
OBJS_C := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SOURCES_C))
OBJS_CXX := $(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(SOURCES_CXX))

# 所有目标文件的集合
OBJS := $(OBJS_C) $(OBJS_CXX)

# 默认目标 (第一个目标)
# .PHONY 声明 'all' 是一个伪目标, 不对应真实文件
.PHONY: all
all: $(TARGET)

# 链接规则: 如何从所有的 .o 文件生成最终的可执行文件
# 依赖于所有的目标文件 $(OBJS)
# 使用 C++ 编译器 (g++) 进行链接
$(TARGET): $(OBJS)
	@echo "==> 链接目标文件生成: $@"
	$(CXX) $^ -o $@ $(LIB_PATHS) $(LDLIBS) $(RPATH)
	@echo "==> 成功生成可执行文件: $(TARGET)"

# 编译规则 (C++): 如何从 .cpp 文件生成 .o 文件
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
	@mkdir -p $(BUILD_DIR)
	@echo "==> 编译 [C++]: $<"
	$(CXX) -c $< -o $@ $(CXXFLAGS)

# 编译规则 (C): 如何从 .c 文件生成 .o 文件
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(BUILD_DIR)
	@echo "==> 编译 [C]  : $<"
	$(CC) -c $< -o $@ $(CFLAGS)

# 清理规则
.PHONY: clean
clean:
	@echo "==> 清理生成的文件..."
	rm -f $(TARGET)
	rm -rf $(BUILD_DIR)
	@echo "==> 清理完成"

# 重新编译
.PHONY: rebuild
rebuild: clean all

